<?php
// +----------------------------------------------------------------------
// | 有理想的地方，地狱都是天堂。
// +----------------------------------------------------------------------
// | Copyright @ df81.com 版权所有
// +----------------------------------------------------------------------
// | 作者: 南国老符 邮箱：1062129401@qq.com
// +----------------------------------------------------------------------

namespace app\api\controller\v1;
use app\api\model\v1\User as apiUserModel;
use app\api\model\v1\Verify as apiVerifyModel;
use think\facade\Cookie;
use think\facade\Lang;
use think\facade\Config;
use think\facade\Db;

class User {
    use \liliuwei\think\Jump;

    /*登录
    @ type类型：bind社交登录...
    @ 返回json值：
    @ success成功，account账号或密码错误，account:verify账号或密码错误且启用验证码，verify验证码错误且启用验证码，lock锁定登录
    */
    public function login(){
        $accountType = input('accountType'); $account = input('account'); $password = input('password'); $verify = input('verify');
        $type = input('type'); $entrance = input('entrance'); $lang = input('lang');

        //加载配置文件以获取后台配置
        Config::load(app()->getBasePath().'admin'.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'app.php');
        //加载语言包
        Lang::load(app()->getBasePath().'admin'.DIRECTORY_SEPARATOR.'lang'.DIRECTORY_SEPARATOR.$lang.'.php');

        if(request()->isPost()){
            $error_times = 1; $lock_time = 0; $lock_ip = 0;
            // 如果登录失败session存在，且不是扫码微信公众号
            if(session('?loginfail')){
                $error_times_arr = explode(':', session('loginfail'));
                $error_times = $error_times_arr[1] + 1;
                $lock_time = $error_times_arr[2] + config('global.lock_minute')*60*1000;
                $lock_ip = $error_times_arr[0];
            }

            //登录失败次数大于后台锁定账号的次数，且不是扫码微信公众号，则锁定一段时间不能登录（后台设置）
            if($error_times > config('global.lock_times') and $lock_time > time() and $lock_ip == request()->ip()){
                return json(['code' => 1002, 'msg' => lang('v_account_lock'), 'data' => $lock_time]);
            }
            
            //登录失败次数大于后台启用验证码的次数，且后台启用校验验证码，且不是扫码微信公众号，则校验验证码
            if($error_times > config('global.verify_times') and $type != 'bind' and config('captcha.user') == 1 and !captcha_check($verify)){
                return json(['code' => 1003, 'msg' => lang('c_verify_error'), 'data' => $verify]);
            }

            //账号密码验证
            $userRs = apiVerifyModel::checkLogin($accountType,$account,$password,$entrance);
            if($userRs == 'error'){
                // 赋值session：登录失败ip、次数和时间
                session('loginfail',request()->ip().':'.$error_times.':'.time());
                // 登录失败次数大于后台启用验证码的次数，则启用验证码
                if($error_times > config('global.verify_times')){
                    return json(['code' => 1004, 'msg' => lang('c_account_password_error'), 'data' => $error_times]);
                }
                // 账号或密码错误
                return json(['code' => 1005, 'msg' => lang('c_account_password_error'), 'data' => $account]);
            }else{
                //如果勾选"保存一月",则持久登陆
                if(input('remember') == '1'){
                    $salt = apiVerifyModel::randStr(16);
                    //第二身份标识
                    $identifier = md5($salt.md5($account.$salt));
                    //持久登录标识
                    $token = md5(uniqid(rand(),true));
                    //持久登录超时时间(1月)
                    Cookie::set('bmkj_auth',"$identifier:$token",2678400);
                    $timeout = time() + 2678400;
                    apiVerifyModel::saveRemember($userRs['id'],$identifier,$token,$timeout);
                }
                //把用户名存入cookie，退出登录后在表单保存用户名信息
                Cookie::set('bmkj_account',$account,2678400);
                Cookie::set('bmkj_nickname',$userRs['nickname'],2678400);
                //删除登录失败session
                session('loginfail', null);
            }

            // 存储token
            $token = signToken($userRs['id'],null,null,$userRs['is_admin'],$userRs['type']);
            session('token',$token);
            //登录成功
            return json(['code' => 200, 'msg' => lang('c_success_login'), 'data' => $token]);
        }
    }

    /*注册：第一步
    * 返回json值：
    * success操作成功，进入下一步，error:lang语言错误，error:agreement未同意注册协议，error:captcha验证码错误
    */
    public function reg(){
        $accountType = input('accountType'); $account = input('account'); $captcha = input('captcha');
        $agreement = input('agreement'); $lang = input('lang');
        //判断session('account')是否存在
        // if(session('?account')) return redirect(url($lang.'/user/save_reg'));
        if(request()->isPost()){
            //语言验证
            if(!preg_match("/^[a-z\s]+$/",$lang)) return json('error:lang');
            //协议验证
            if($agreement != 1) return json('error:agreement');
            //账号验证
            $accountRs = apiVerifyModel::account($accountType,$account,'reg');
            if($accountRs != 'success') return json($accountRs);
            //验证码验证
            $captchaRs = apiVerifyModel::captcha($account,$captcha);
            if($captchaRs != 'success') return json($captchaRs);
            
            session('accountType',$accountType);
            session('account',$account);
            return json('success');
        }
    }

    /*注册：最后一步
    @ 返回json值，success成功，error注册失败，lang语言错误，agreement未同意注册协议，password密码格式错误，vpassword密码不一致，captcha验证码错误
    */
    public function save_reg(){
        $password = input('password'); $vpassword = input('vpassword'); $lang = input('lang');
        //判断session('account')是否存在
        if(!session('?account') or !session('?accountType')) return redirect(url($lang.'/user/reg'));
        $accountType = session('accountType'); $account = session('account');
        if(request()->isPost()){
            //密码验证：密码为6-20位，且必须包含字母和数字
            if(!preg_match('/^(?=.*\d)(?=.*[a-zA-Z]).{6,20}$/',$password)) return json('error:password');
            //确认密码验证
            if($vpassword != $password) return json('error:vpassword');
            $this->do_reg($accountType,$account,$password,$lang);
            return json('success');
        }
    }

    /*会员注册
    * accountType 来路：qq，wechat微信，weibo新浪微博，mobile手机，email
    * account 手机/邮箱账号
    * password 密码
    * lang 语言
    */
    public function do_reg($accountType,$account,$password,$lang){
        //是否存在前端会员组
        $authGroupWhere[] = ['lang','=',$lang]; $authGroupWhere[] = ['is_admin','=',0]; $authGroupWhere[] = ['signid','=',1];
        $authGroupRs = Db::name('auth_group')->where($authGroupWhere)->order('sequence desc')->find();
        if(empty($authGroupRs)){
            return json('error:group');
        }
        /*注册会员 开始*/
        //推荐人ID
        $parentid = $level = 0;
        if(cookie('?bmkj_spread')){
            $userRs = Db::name('user')->where('spread',cookie('bmkj_spread'))->field('id,parentid,level')->find();
            if(!empty($userRs)){
                $parentid = $userRs['id'];
                $level = $userRs['level'] + 1;
            }
        }
        //来路
        $avatar = NULL; $socialRs = session('socialRs');
        switch ($accountType) {
            case 'mobile':
                $data['mobile'] = $account;
                $data['password'] = md5($password);
                $nickname = 'user'.substr($account,0,3).substr($account,-3,3);
                break;
            case 'email':
                $data['email'] = $account;
                $data['password'] = md5($password);
                $nickname = strstr($account,'@',true).rand(10,999);
                break;
        }

        // 社交类型
        if(!empty($socialRs)){
            switch ($socialRs['type']) {
                case 'qq':
                    $data['qqid'] = $socialRs['openid'];
                    $nickname = $socialRs['nickname'];
                    $avatar = $socialRs['avatar'];
                    break;
                case 'wechat':
                    // 注册微信开放平台才有unionid
                    // $data['wx_unionid'] = $socialRs['unionid'];
                    $data['openid'] = $socialRs['openid'];
                    $data['gender'] = $socialRs['sex'];
                    if(!empty($socialRs['nickname'])) $nickname = $socialRs['nickname'];
                    $avatar = $socialRs['headimgurl'];
                    break;
                case 'weibo':
                    $data['weiboid'] = $socialRs['openid'];
                    if(!empty($socialRs['screen_name'])) $nickname = $socialRs['screen_name'];
                    $avatar = $socialRs['avatar_hd'];
                    break;
            }
        }
        
        
        $data['parentid'] = $parentid;
        $data['level'] = $level;
        $data['nickname'] = $nickname;
        $data['avatar'] = $avatar;
        $data['addtime'] = time();
        $data['ip'] = request()->ip();
        $data['score'] = $authGroupRs['give_score'];
        $data['balance'] = $authGroupRs['give_price'];
        $data['spread'] = substr(date('Y'),2).substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8).date('mdHis');

        $userId = apiUserModel::edit($lang,0,$data);
        if(!is_numeric($userId) or $userId < 1){
            return json('error');
        }
        /*注册会员 结束*/
        //写入session
        session('userid',$userId);
        session('nickname',$nickname);
        //获取用户组
        $groupRs = Db::name("auth_group_access")->where('uid',$userId)->find();
        $groupid = $groupRs['group_id'];
        $rulesRs = Db::name("auth_group")->where('id',$groupid)->find();
        session('groupid',$groupid);
        session('group_discount',$rulesRs['discount']);
        session('is_admin',$rulesRs['is_admin']);
        //删除注册失败session
        session('regfail', null);
        //删除accountType和account
        session('accountType', null);
        session('account', null);
        return true;
    }

    /*社交绑定或注册*/
    public function bind(){
        if(!session('?socialRs')) return redirect('user/login');
        $socialRs = session('socialRs'); $social = input('social');
        $accountType = input('accountType'); $account = input('account'); $password = input('password');
        switch ($social) {
            case 'qq':
                $nickname = $socialRs['nickname'];
                //绑定账号
                $data['qqid'] = $socialRs['id'];
                break;
            case 'wechat':
                $nickname = $socialRs['nickname'];
                //绑定账号
                $data['unionid'] = $socialRs['unionid'];
                $data['openid'] = $socialRs['openid'];
                break;
            case 'weibo':
                $nickname = $socialRs['screen_name'];
                //绑定账号
                $data['weiboid'] = $socialRs['id'];
                break;
        }
        if(request()->isPost()){
            if(!in_array($accountType,array('mobile','email'))) return 0;
            switch ($accountType) {
                case 'mobile':
                    $userWhere[] = ['mobile','=',$account];
                    break;
                case 'email':
                    $userWhere[] = ['email','=',$account];
                    break;
            }
            $userWhere[] = ['password','=',md5($password)];
            $userRs = Db::name('user')->where($userWhere)->find();
            if(empty($userRs)){//账号或密码有误
                return 0;
            }else{
                //绑定社交账号
                Db::name('user')->where('id',$userRs['id'])->update($data);
                session('userid',$userRs['id']);
                session('nickname',$nickname);
                return json($userRs);
            }
        }
    }

    /*找回密码
    @ 返回json值，success成功，$accountRs控制器verify的返回值，captcha验证码错误
    */
    public function getpwd(){
        if(request()->isPost()){
            $accountType = input('accountType'); $account = input('account'); $captcha = input('captcha');
            //账号验证
            $accountRs = apiVerifyModel::account($accountType,$account,'getpwd');
            if($accountRs != 'success') return json($accountRs);
            //验证码验证
            $captchaRs = apiVerifyModel::captcha($account,$captcha);
            if($captchaRs != 'success') return json($captchaRs);
            //读取用户信息
            switch ($accountType) {
                case 'mobile':
                    $userWhere[] = ['mobile','=',$account];
                    break;
                case 'email':
                    $userWhere[] = ['email','=',$account];
                    break;
            }
            $userRs = Db::name('user')->where($userWhere)->find();
            session('userid',$userRs['id']);
            session('nickname',$userRs['nickname']);
            session('oldpassword',1);
            //返回json
            return json('success');
        }
    }

    /*重置、修改密码
    @ 返回json值，success成功，error失败，password密码错误，vpassword密码不一致，oldpassword原密码不正确
    */
    public function setpwd(){
        if(!session('?userid')) return json(lang('c_login_again'));
        if(request()->isPost()){
            $lang = input('lang'); $password = input('password'); $vpassword = input('vpassword'); $oldpassword = md5(input('oldpassword'));

            if(!preg_match("/^[a-z\s]+$/",$lang)) $lang = config('lang.default_lang');
            //加载语言包
            Lang::load(app()->getBasePath().$lang.DIRECTORY_SEPARATOR.'lang'.DIRECTORY_SEPARATOR.$lang.'.php');

            //密码验证：密码为6-20位，且必须包含字母和数字
            if(!preg_match('/^(?=.*\d)(?=.*[a-zA-Z]).{6,20}$/',$password)) return json(lang('y_password_require'));
            //确认密码验证
            if($vpassword != $password) return json(lang('y_password_confirm'));
            $userWhere[] = ['id','=',session('userid')];
            //旧密码验证
            if(!session('?oldpassword')){
                $userRs = Db::name('user')->where($userWhere)->find();
                if($oldpassword != $userRs['password'] and !empty($userRs['password'])) return json(lang('c_oldpassword_error'));
            }
            //修改密码
            Db::name('user')->where($userWhere)->update(['password' => md5($password)]);
            session(null,'oldpassword');
            //返回json
            return json('success');
        }
    }

    /*修改个人资料
    * 返回json值：error失败，success成功，lang:error语言错误，nickname:error昵称格式有误，qq:error表示QQ格式有误
    */
    public function edit(){
        if(!session('?userid')) return json(lang('c_login_again'));

        if(request()->isPost()){
            $lang = input('lang'); $nickname = input('nickname'); $gender = input('gender'); $qq = input('qq');

            if(!preg_match("/^[a-z\s]+$/",$lang)) $lang = config('lang.default_lang');
            //加载语言包
            Lang::load(app()->getBasePath().$lang.DIRECTORY_SEPARATOR.'lang'.DIRECTORY_SEPARATOR.$lang.'.php');

            if(!preg_match("/^[a-z\s]+$/",$lang)) return json(lang('c_lang_error'));
            // if(!preg_match("/^[1-9]\d{4,10}$/",$qq)) return json(lang('v_qq_tips'));

            $data['nickname'] = $nickname;
            $data['gender'] = $gender;
            $data['qq'] = $qq;
            $data['wechat'] = input('wechat');
            $data['telephone'] = input('telephone');
            $data['realname'] = input('realname');
            $data['birthday'] = input('birthday');
            $data['avatar'] = input('avatar');
            $userId = apiUserModel::edit($lang,session('userid'),$data);
            if(!is_numeric($userId) or $userId < 1) return json(lang('c_fail'));
            return json('success');
        }
    }

    /*前端会员中心修改：用户名、手机、邮箱*/
    public function edit_account(){
        if(request()->isPost()){
            $accountType = input('accountType'); $captcha = input('captcha');
            $username = input('username'); $mobile = input('mobile'); $email = input('email');
            switch ($accountType) {
                case 'username':
                    $account = $username;
                    $data['username'] = $username;
                    break;
                case 'mobile':
                    $account = $mobile;
                    $data['mobile'] = $mobile;
                    break;
                case 'email':
                    $account = $email;
                    $data['email'] = $email;
                    break;
            }
            //账号验证
            $accountRs = apiVerifyModel::account($accountType,$account,'edit');
            if($accountRs != 'success') return json($accountRs);
            //验证码验证
            if(in_array($accountType, array('mobile','email'))){
                $captchaRs = apiVerifyModel::captcha($account,$captcha);
                if($captchaRs != 'success') return json($captchaRs);
            }
            //更新user表
            $userId = apiUserModel::edit('',session('userid'),$data);
            if(!is_numeric($userId) or $userId < 1) return json('error');
            return json('success');
        }else{
            return json('error');
        }
    }

    /**登录验证
    * @username 用户名
    * @password 已MD5过的密码
    **/
    public function checkLogin($username,$password){
        //账号密码是否正确
        $userWhere[] = ['username','=',$username]; $userWhere[] = ['password','=',$password];
        $userRs = Db::name('user')->where($userWhere)->find();
        if(!empty($userRs)){
            return $userRs;
        }else{
            return false;
        }
    }

    /*退出
    * 返回json值：error失败，success成功
    */
    public function logout(){
        session(null);
        cookie('bmkj_auth',null);
        return json('success');
    }
}